library(sf)
library(tidyverse)
library(ggthemes)
library(ggspatial)
library(units)
library(nngeo)
greenspaces <- st_read("greenspaces.kml", quiet = TRUE)
schools <- st_read("schools.kml", quiet = TRUE)
township <- st_read("township.kml", quiet = TRUE)
weibo <- st_read("weibo.kml", quiet = TRUE)
china <- "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
greenspaces <- greenspaces %>%
  st_transform(china)
schools <- schools %>%
  st_transform(china)
township <- township %>%
  st_transform(china)
weibo <- weibo %>%
  st_transform(china)
schools_buffer <- st_buffer(schools, dist = 100) %>%
  st_union()

MAP 01

Map 1 shows the number and proportion of Weibo posts within 100m radius, or “buffers”, of a school. It appears that there are not many Weibo posts within 100m radius of schools.

ggplot(schools_buffer) +
  geom_sf() +
  theme_map()

weibo_schools <- weibo[schools_buffer,]
  
ggplot(schools_buffer) +
  geom_sf() +
  geom_sf(data = weibo_schools, 
          color = "#92E0EB", 
          size = 0.05) +
  theme_map()

weibo <- weibo %>%
  st_join(weibo_schools) %>%
  mutate(by_schools = !is.na(Name.y))
n_schools_weibo <- sum(weibo$by_schools)
n_schools_weibo
## [1] 281
n_weibo <- length(weibo$by_schools)
pct_schools_weibo <- n_schools_weibo / n_weibo
pct_schools_weibo
## [1] 0.007155225
left_side  <- st_bbox(weibo)$xmin
top_side <- st_bbox(weibo)$ymax

ggplot(township) +
  geom_sf(fill = "NA", color = "black") +
  geom_sf(data = weibo, size = 0.05,
          aes(color = by_schools)) +
  scale_color_manual(values = c("#92E0EB", "#EC3FB5"),
          name = "weibo in jiaxing\nby distance to a school", 
          labels = c("no school within 100m",
                     "school within 100m")) +
  annotation_scale(location = "br") +
  annotation_north_arrow(location = "tr",
                         style = north_arrow_minimal()) +
  annotate(geom = "text", x = left_side, 
           y = top_side, 
           label = paste("of the", 
                         prettyNum(n_weibo, big.mark = ","),
                         "weibo in jiaxing\n", 
                         prettyNum(n_schools_weibo, big.mark = ","),
                         " (", 
                         prettyNum(100*pct_schools_weibo, digits = 0),
                         "%) of weibo in jiaxing are within 100\nmeters of a school.",
                         sep = ""),
           hjust = 0, vjust = 0, size = 3) +
  theme_map() +
  theme(panel.background = element_rect(fill = "cornsilk1"),
        legend.background = element_rect(fill = alpha("white", 0.7), 
                                         color = "gray")) +
  theme(legend.position = "right") 

MAP02

Map 2 shows the average distance between a Weibo post and a school. Here, we observe that the average distance of a school from a Weibo post is 350m.

schools <- schools %>%
  mutate(weibo_dist = st_nn(schools, weibo, 
                           returnDist = TRUE)$dist) %>%
  mutate(weibo_dist = as.numeric(weibo_dist))
## projected points
avg_weibo_dist <- mean(schools$weibo_dist)
avg_weibo_dist
## [1] 350.2111
right_side <- st_bbox(township)$xmax
left_side  <- st_bbox(township)$xmin
top_side <- st_bbox(township)$ymax
bottom_side <- st_bbox(township)$ymin


ggplot(township) +
  geom_sf(fill = "NA", color = "black") +
  geom_sf(data = schools, size = 0.1,
          aes(color = weibo_dist)) +
  coord_sf(xlim = c(left_side, right_side+1000), 
           ylim = c(bottom_side, top_side+1000), expand = FALSE) +
  scale_color_viridis_c(name = 
                          "schools in jiaxing meters\nby distance to a weibo") +
  annotation_scale(location = "br") +
  annotation_north_arrow(location = "tr",
                         style = north_arrow_minimal()) +
  annotate(geom = "text", x = left_side, 
           y = top_side, 
           label = paste("on average, a school in jiaxing is meter\nis ", 
                         prettyNum(avg_weibo_dist, digits = 3),
                         " meters from a weibo.",
                         sep = ""),
           hjust = -0.2, vjust = 1, size = 3) +
  theme_map() +
  theme(panel.background = element_rect(fill = "cornsilk1"),
        legend.background = element_rect(fill = alpha("white", 0.7), 
                                         color = "gray"))+
  theme(legend.position = "right") 

MAP03

Map 3 visualizes the number of Weibo posts in each township in relation to each other using a chloropleth map, allowing the reader to contextualize the volumes of posts. The average number of Weibo posts in each township is calculated using the mean function.

township <- township %>%
  mutate(n_weibo = lengths(st_covers(township, weibo)))

mean(township$n_weibo)
## [1] 400.398
left_side  <- st_bbox(weibo)$xmin
top_side <- st_bbox(weibo)$ymax

ggplot(township) +
  annotation_map_tile(zoomin = 0, progress = "none", type = "osmgrayscale") +
  geom_sf() +
  labs(caption = "Map tiles and data by OpenStreetMap")+
  geom_sf(color = NA, 
          aes(fill = n_weibo)) +
  scale_fill_viridis_c(name = "Jiaxing townships\nby number of Weibo posts",
                       breaks = breaks <- seq(0, 10000, by = 500),
                       labels = paste(prettyNum(breaks, big.mark = ","),
                                      "Weibo posts")) +
  annotation_scale(location = "br") +
  annotation_north_arrow(location = "tr",
                         style = north_arrow_minimal()) +
  annotate(geom = "text", x = left_side, 
           y = top_side, 
           label = paste("Average number:", 
                         prettyNum(mean(township$n_weibo), big.mark = ","),
                         "Weibo posts in Jiaxing\n", 
                         sep = ""),
           hjust = 0, vjust = 0, size = 3) +

theme_map() +
  theme(legend.background = element_rect(fill = alpha("white", 0.5), 
                                         color = "gray")) +
  theme(legend.position = "right") 
## Loading required namespace: raster

MAP04

Map 4 visualizes the average density of Weibo posts per sq km in each township in relation to each other using a chloropleth map, allowing the reader to contextualize the volumes of posts. The average density number of Weibo posts in each township is calculated by first calculating the area of each township using st_area(), then dividing the number of posts by that area.

township <- township %>%
  mutate(area = set_units(st_area(township), km^2)) %>%
  mutate(weibo_dens = as.numeric(n_weibo / area))

ggplot(township[which(township$weibo_dens > 0.5),]) +
  annotation_map_tile(zoomin = 0, progress = "none", type = "osmgrayscale") +
  geom_sf() +
  labs(caption = "Map tiles and data by OpenStreetMap")+
  geom_sf(color = NA, 
          aes(fill = weibo_dens)) +
    scale_fill_viridis_c(name = 
                           "Jiaxing Townships\nby weibo posts density",
                         breaks = breaks <- c(0.01, 0.1, 1, 10, 100, 1000), trans = "log",
                       labels = paste(prettyNum(breaks, big.mark = ","),
                                      "posts per square km")) +
  annotation_scale(location = "br") +
  annotation_north_arrow(location = "tr",
                         style = north_arrow_minimal()) +
theme_map() +
  theme(legend.position = "right",
    legend.background = element_rect(fill = alpha("white", 0.5), 
                                         color = "gray"))

MAP05

Map 5 shows that 26 of the Jiaxing townships contain or overlap with a greenspace.

MAP06

Map 6 examines the number of Weibo posts within a greenspace. The result is 5.5% of the posts occur within a greenspace.

weibo_green <- weibo[greenspaces,] 

n_green_weibo <- length(weibo_green$Name.x)

n_weibo <- length(weibo$by_schools)

pct_green_weibo <- n_green_weibo / n_weibo

left_side  <- st_bbox(weibo)$xmin
top_side <- st_bbox(weibo)$ymax

ggplot(township) +
  geom_sf(fill = NA, color = NA) +
  geom_sf(data = greenspaces, fill = "lightgreen", color = NA) +
  geom_sf(data = township, fill = NA) +
  geom_sf(data = weibo, size = 0.1,
          aes(color = "darkgreen")) +
  geom_sf(data = weibo_green, size = 0.01,
          aes(color = "chocolate1")) +
    scale_color_manual(values = c("chocolate1", "darkgreen"),
          name = "Weibo data\ngreen space in Jiaxing", 
          labels = c("Within greenspace",
                     "Not within greenspace")) +
  annotation_scale(location = "br") +
  annotation_north_arrow(location = "tr",
                         style = north_arrow_minimal()) +
  annotate(geom = "text", x = left_side, 
           y = top_side, 

           label = paste("Of the ", 
                         prettyNum(n_weibo, big.mark = ","),
                         " weibo in Jiaxing\n", 
                         prettyNum(n_green_weibo, big.mark = ","),
                         " (", 
                         prettyNum(100*pct_green_weibo, digits = 2),
                         "%) are within green space.",
                         sep = ""),
           hjust = 0, vjust = 0, size = 3) +
  theme_map() +
  theme(panel.background = element_rect(fill = "cornsilk1"),
        legend.background = element_rect(fill = alpha("white", 0.5), 
                                         color = "gray")) +
  theme(legend.position = "right") 

CONTRIBUTION STATEMENT

The three of us worked or struggled equally together with this assignment having no programming background. We were very engaged within the group in sharing problems and trying help each other work out the mapping prompts we decided to take on. The three of us sat together to synthesize the final html document for submission. We are so happy to have made it despite encountering issue at the last step! 10 points each, hooray!